﻿// <copyright file="ChartLogarithmicScaleTest.cs" company="Oleg V. Polikarpotchkin">
// Copyright © 2008 Oleg V. Polikarpotchkin. All Right Reserved
// </copyright>
// <author>Oleg V. Polikarpotchkin</author>
// <email>ov-p@yandex.ru</email>
// <date>2008-12-29</date>
// <summary>WPF OpenWPFChart library. ChartLogarithmicScale class Test.</summary>
// <revision>$Id$</revision>

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenWPFChart.Parts;

namespace Tests
{
    /// <summary>
    ///This is a test class for ChartLogarithmicScaleTest and is intended
    ///to contain all ChartLogarithmicScaleTest Unit Tests
    ///</summary>
	[TestClass()]
	public class ChartLogarithmicScaleTest
	{
		#region TestContext
		private TestContext testContextInstance;
		/// <summary>
		///Gets or sets the test context which provides
		///information about and functionality for the current test run.
		///</summary>
		public TestContext TestContext
		{
			get
			{
				return testContextInstance;
			}
			set
			{
				testContextInstance = value;
			}
		}
		#endregion TestContext

		#region Additional test attributes
		// 
		//You can use the following additional attributes as you write your tests:
		//
		//Use ClassInitialize to run code before running the first test in the class
		//[ClassInitialize()]
		//public static void MyClassInitialize(TestContext testContext)
		//{
		//}
		//
		//Use ClassCleanup to run code after all tests in a class have run
		//[ClassCleanup()]
		//public static void MyClassCleanup()
		//{
		//}
		//
		//Use TestInitialize to run code before running each test
		//[TestInitialize()]
		//public void MyTestInitialize()
		//{
		//}
		//
		//Use TestCleanup to run code after each test has run
		//[TestCleanup()]
		//public void MyTestCleanup()
		//{
		//}
		//
		#endregion

		/// <summary>
		/// A test for parametrizied constructor
		///</summary>
		[TestMethod()]
		public void ConstructorTest()
		{
			ChartLogarithmicScale target = new ChartLogarithmicScale(1.0, 10.0, 300);

			double actual = target.ToPixels(1.0);
			Assert.AreEqual(0.0, actual);

			actual = target.ToPixels(10.0);
			Assert.AreEqual(300.0, actual);

			target = new ChartLogarithmicScale(1.0, 333, 300);
			actual = target.ToPixels(333);
			Assert.AreEqual(300.0, actual);
		}

		/// <summary>
		/// A test for DecimateTick
		/// DecimateTick presents tick value as a*10^n where n - any intger; a - integer, 1 &le; a &lt; 10.
		///</summary>
		[TestMethod()]
		[DeploymentItem("OpenWPFChart.Parts.dll")]
		public void DecimateTickTest()
		{
			double power; // = 10^n
			int a = ChartLogarithmicScale_Accessor.DecimateTick(1.0, out power); // (int)a
			Assert.AreEqual(1.0, power);
			Assert.AreEqual(1, a);

			a = ChartLogarithmicScale_Accessor.DecimateTick(1.2, out power);
			Assert.AreEqual(1.0, power);
			Assert.AreEqual(1, a);

			a = ChartLogarithmicScale_Accessor.DecimateTick(5.2, out power);
			Assert.AreEqual(1.0, power);
			Assert.AreEqual(5, a);
		}

		/// <summary>
		///A test for adjacentTick
		///</summary>
		[TestMethod()]
		[DeploymentItem("OpenWPFChart.Parts.dll")]
		public void adjacentTickTest()
		{
			// Next adjacent tick
			double tick = ChartLogarithmicScale_Accessor.adjacentTick(5.0, true);
			Assert.AreEqual(5.0, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(5.1, true);
			Assert.AreEqual(6.0, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(9.0, true);
			Assert.AreEqual(9.0, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(9.1, true);
			Assert.AreEqual(10.0, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(10.0, true);
			Assert.AreEqual(10.0, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(15.0, true);
			Assert.AreEqual(20.0, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(21.0, true);
			Assert.AreEqual(30.0, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(30.0, true);
			Assert.AreEqual(30.0, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(40.0, true);
			Assert.AreEqual(40.0, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(95.0, true);
			Assert.AreEqual(100.0, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(100.0, true);
			Assert.AreEqual(100.0, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(101.0, true);
			Assert.AreEqual(200.0, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(0.5, true);
			Assert.AreEqual(0.5, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(0.51, true);
			Assert.AreEqual(0.6, tick, 1e-10);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(0.05, true);
			Assert.AreEqual(0.05, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(0.051, true);
			Assert.AreEqual(0.06, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(0.091, true);
			Assert.AreEqual(0.1, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(0.1, true);
			Assert.AreEqual(0.1, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(0.01, true);
			Assert.AreEqual(0.01, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(0.011, true);
			Assert.AreEqual(0.02, tick);

			// Prev adjacent tick
			tick = ChartLogarithmicScale_Accessor.adjacentTick(5.0, false);
			Assert.AreEqual(5.0, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(5.1, false);
			Assert.AreEqual(5.0, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(9.0, false);
			Assert.AreEqual(9.0, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(9.1, false);
			Assert.AreEqual(9.0, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(10.0, false);
			Assert.AreEqual(10.0, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(15.0, false);
			Assert.AreEqual(10.0, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(95.0, false);
			Assert.AreEqual(90.0, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(100.0, false);
			Assert.AreEqual(100.0, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(101.0, false);
			Assert.AreEqual(100.0, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(0.5, false);
			Assert.AreEqual(0.5, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(0.51, false);
			Assert.AreEqual(0.5, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(0.05, false);
			Assert.AreEqual(0.05, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(0.051, false);
			Assert.AreEqual(0.05, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(0.091, false);
			Assert.AreEqual(0.09, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(0.1, false);
			Assert.AreEqual(0.1, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(0.11, false);
			Assert.AreEqual(0.1, tick);
			tick = ChartLogarithmicScale_Accessor.adjacentTick(0.01, false);
			Assert.AreEqual(0.01, tick);
		}

		/// <summary>
		///A test for Ticks
		///</summary>
		[TestMethod()]
		public void TicksTest()
		{
			//TickRange start=10, stop=1
			//10 long 9 8 7 6 5 4 3 2 1 long
			ChartLogarithmicScale target = new ChartLogarithmicScale()
			{
				Start = 10.0,
				Stop = 1.0
			};
			List<ScaleTick> expected = new List<ScaleTick>()
			{
				new ScaleTick(10.0, true),
				new ScaleTick(9.0, false),
				new ScaleTick(8.0, false),
				new ScaleTick(7.0, false),
				new ScaleTick(6.0, false),
				new ScaleTick(5.0, false),
				new ScaleTick(4.0, false),
				new ScaleTick(3.0, false),
				new ScaleTick(2.0, false),
				new ScaleTick(1.0, true)
			};
			List<ScaleTick> actual = target.Ticks().ToList();
			CollectionAssert.AreEqual(expected, actual);

			//TickRange start=100, stop=1
			//100 long 90 80 70 60 50 40 30 20 10 long 9 8 7 6 5 4 3 2 1 long
			target.Start = 100.0;
			target.Stop = 1.0;
			expected = new List<ScaleTick>()
			{
				new ScaleTick(100.0, true),
				new ScaleTick(90.0, false),
				new ScaleTick(80.0, false),
				new ScaleTick(70.0, false),
				new ScaleTick(60.0, false),
				new ScaleTick(50.0, false),
				new ScaleTick(40.0, false),
				new ScaleTick(30.0, false),
				new ScaleTick(20.0, false),
				new ScaleTick(10.0, true),
				new ScaleTick(9.0, false),
				new ScaleTick(8.0, false),
				new ScaleTick(7.0, false),
				new ScaleTick(6.0, false),
				new ScaleTick(5.0, false),
				new ScaleTick(4.0, false),
				new ScaleTick(3.0, false),
				new ScaleTick(2.0, false),
				new ScaleTick(1.0, true)
			};
			actual = target.Ticks().ToList();
			CollectionAssert.AreEqual(expected, actual);

			//TickRange start=3.1, stop=1
			//3 2 1 long
			target.Start = 3.1;
			target.Stop = 1.0;
			expected = new List<ScaleTick>()
			{
				new ScaleTick(3.0, false),
				new ScaleTick(2.0, false),
				new ScaleTick(1.0, true)
			};
			actual = target.Ticks().ToList();
			CollectionAssert.AreEqual(expected, actual);

			//TickRange start=100, stop=10
			//100 long 90 80 70 60 50 40 30 20 10 long
			target.Start = 100.0;
			target.Stop = 10.0;
			expected = new List<ScaleTick>()
			{
				new ScaleTick(100.0, true),
				new ScaleTick(90.0, false),
				new ScaleTick(80.0, false),
				new ScaleTick(70.0, false),
				new ScaleTick(60.0, false),
				new ScaleTick(50.0, false),
				new ScaleTick(40.0, false),
				new ScaleTick(30.0, false),
				new ScaleTick(20.0, false),
				new ScaleTick(10.0, true),
			};
			actual = target.Ticks().ToList();
			CollectionAssert.AreEqual(expected, actual);

			//TickRange start=1, stop=0.1
			//1 long 0.9 0.8 0.7 0.6 0.5 0.4 0.3 0.2 0.1 long
			target.Start = 1.0;
			target.Stop = 0.1;
			expected = new List<ScaleTick>()
			{
				new ScaleTick(1.0, true),
				new ScaleTick(0.9, false),
				new ScaleTick(0.8, false),
				new ScaleTick(0.7, false),
				new ScaleTick(0.6, false),
				new ScaleTick(0.5, false),
				new ScaleTick(0.4, false),
				new ScaleTick(0.3, false),
				new ScaleTick(0.2, false),
				new ScaleTick(0.1, true)
			};
			actual = target.Ticks().ToList();
			CollectionAssert.AreEqual(expected, actual, new TickComparer());

			//TickRange start=0.1, stop=0.01
			//0.1 long 0.09 0.08 0.07 0.06 0.05 0.04 0.03 0.02 0.01 long
			target.Start = 0.1;
			target.Stop = 0.01;
			expected = new List<ScaleTick>()
			{
				new ScaleTick(0.1, true),
				new ScaleTick(0.09, false),
				new ScaleTick(0.08, false),
				new ScaleTick(0.07, false),
				new ScaleTick(0.06, false),
				new ScaleTick(0.05, false),
				new ScaleTick(0.04, false),
				new ScaleTick(0.03, false),
				new ScaleTick(0.02, false),
				new ScaleTick(0.01, true)
			};
			actual = target.Ticks().ToList();
			CollectionAssert.AreEqual(expected, actual, new TickComparer());

			//TickRange start=0.001, stop=0.0001
			//0.001 long 0.0009 0.0008 0.0007 0.0006 0.0005 0.0004 0.0003 0.0002 0.0001 long
			target.Start = 0.001;
			target.Stop = 0.0001;
			expected = new List<ScaleTick>()
			{
				new ScaleTick(0.001, true),
				new ScaleTick(0.0009, false),
				new ScaleTick(0.0008, false),
				new ScaleTick(0.0007, false),
				new ScaleTick(0.0006, false),
				new ScaleTick(0.0005, false),
				new ScaleTick(0.0004, false),
				new ScaleTick(0.0003, false),
				new ScaleTick(0.0002, false),
				new ScaleTick(0.0001, true)
			};
			actual = target.Ticks().ToList();
			CollectionAssert.AreEqual(expected, actual, new TickComparer());

			//TickRange start=11, stop=0.1
			//10 long 9 8 7 6 5 4 3 2 1 long 0.9 0.8 0.7 0.6 0.5 0.4 0.3 0.2 0.1 long
			target.Start = 11.0;
			target.Stop = 0.1;
			expected = new List<ScaleTick>()
			{
				new ScaleTick(10.0, true),
				new ScaleTick(9.0, false),
				new ScaleTick(8.0, false),
				new ScaleTick(7.0, false),
				new ScaleTick(6.0, false),
				new ScaleTick(5.0, false),
				new ScaleTick(4.0, false),
				new ScaleTick(3.0, false),
				new ScaleTick(2.0, false),
				new ScaleTick(1.0, true),
				new ScaleTick(0.9, false),
				new ScaleTick(0.8, false),
				new ScaleTick(0.7, false),
				new ScaleTick(0.6, false),
				new ScaleTick(0.5, false),
				new ScaleTick(0.4, false),
				new ScaleTick(0.3, false),
				new ScaleTick(0.2, false),
				new ScaleTick(0.1, true)
			};
			actual = target.Ticks().ToList();
			CollectionAssert.AreEqual(expected, actual, new TickComparer());

			//TickRange start=10, stop=1, TickMask=Main
			//10 long 9 8 7 6 5 4 3 2 1 long
			target.Start = 10.0;
			target.Stop = 1.0;
			target.TickMask = LogarithmicScaleTicks.Main;
			expected = new List<ScaleTick>()
			{
				new ScaleTick(10.0, true),
				new ScaleTick(5.0, false),
				new ScaleTick(2.0, false),
				new ScaleTick(1.0, true)
			};
			actual = target.Ticks().ToList();
			CollectionAssert.AreEqual(expected, actual);
		}

		/// <summary>
		/// Compare two AxisTick on equality.
		/// </summary>
		class TickComparer : IComparer
		{
			public int Compare(object x, object y)
			{
				if (x.GetType() != typeof(ScaleTick) || y.GetType() != typeof(ScaleTick))
					return object.Equals(x, y) ? 0 : 1;
				ScaleTick xTick = (ScaleTick)x;
				ScaleTick yTick = (ScaleTick)y;
				if (xTick.IsLong != yTick.IsLong)
					return 1;
				double xValue = (double)xTick.Value, yValue = (double)yTick.Value;
				double delta = 2 * Math.Abs((xValue - yValue) / (xValue + yValue));
				return delta < 10.0e-10 ? 0 : 1;
			}
		}

		/// <summary>
		///A test for ToPixels
		///</summary>
		[TestMethod()]
		public void ToPixelsTest()
		{
			ChartLogarithmicScale target = new ChartLogarithmicScale()
			{
				Start = 10.0,
				Stop = 1.0
			};
			double actual = target.ToPixels(10.0);
			Assert.AreEqual(0.0, actual);
		}

		/// <summary>
		///A test for FromPixels
		///</summary>
		[TestMethod()]
		public void FromPixelsTest()
		{
			ChartLogarithmicScale target = new ChartLogarithmicScale()
			{
				Start = 10.0,
				Stop = 1.0
			};
			double actual = (double)target.FromPixels(0.0);
			Assert.AreEqual(10.0, actual);
		}
	}
}
